<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1.片元着色器绘制圆-图片渐显渐隐</title>
    <style>
        canvas{
            border:1px solid #aaa;
            margin: 0 auto;
            display: block;
        }
    </style>
</head>
<body>
    <canvas width="1000" height="554"></canvas>
    <script src="/common/lib/gl-renderer.js"></script>
    <script type="module">
        import { loadImage } from "/common/lib/utils.js";

        (async function(){
            /**
             * gl-renderer 在 WebGL 底层的基础上进行了一些简单的封装，以便于我们将重点放在提供几何数据、设置变量和编写 Shader 上，不用因为创建 buffer 等细节而分心
             * 第一步: 创建 Renderer 对象
             * 第二步: 创建并启用 WebGL 程序
             * 第三步: 设置 uniform 变量
             * 第四步: 将顶点数据送入缓冲区
             * 第五步: 渲染
            */
            const canvas = document.querySelector('canvas'); 
            const renderer = new GlRenderer(canvas);
            
            // 第二步

            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;
                
                void main() {
                    gl_PointSize = 1.0;
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1, 1);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                precision highp float;
                #endif

                uniform sampler2D tMap;
                uniform vec2 uResolution;
                uniform float uTime;
                varying vec2 vUv;

                float random (vec2 st) {
                    return fract(sin(dot(st.xy,
                                        vec2(12.9898,78.233)))*
                        43758.5453123);
                }

                void main() {
                    vec2 uv = vUv;
                    // uv.y *= 1000.0 / 554.0;
                    // 纹理坐标分成100份
                    vec2 st = uv * vec2(100.0,55.4);
                    // 每一份中计算距离，范围0-0.5
                    float d = distance(fract(st), vec2(0.5));
                    // 每一份生成一个随机数，加上时间，p随时间变化
                    float p = uTime + random(floor(st));
                    // 阴影随p的变化，范围0-1
                    float shading = 0.5 + 0.5 * sin(p);
                    // 因为阴影随P变化了，所以平滑阶梯函数的值也是随P变化的。
                    d = smoothstep(d, d + 0.01, 1.0 * shading);
                    vec4 color = texture2D(tMap, vUv);
                    // clamp(x,min,max)函数，如果x小于min，返回min；x大于max，返回max；如果max<min，返回0；否则返回x。
                    // shading范围0-1，当d为0，也就是每一份中的距离如果超过1.0 * shading+0.01，那么就是返回0，否则相反；
                    // d为0时，表示半径大的颜色值都是0，也就是呈现黑色，否则就根据d + 1.0 * shading的值进行变化
                    gl_FragColor.rgb = color.rgb * clamp(0.5, 1.2, d + 1.0 * shading);
                    gl_FragColor.a = color.a;
                }
            `;
            const program = renderer.compileSync(fragment,vertex);
            renderer.useProgram(program);
    
            // 第三步
            const texture = await renderer.loadTexture("https://p1.ssl.qhimg.com/t01cca5849c98837396.jpg");
            renderer.uniforms.tMap = texture;
            renderer.uniforms.uTime = 0

            // 第四步
            renderer.setMeshData([
                {
                    positions:[
                        [-1, -1], 
                        [-1, 1], 
                        [1, 1], 
                        [1, -1]
                    ],
                    attributes:{
                        uv:[
                            [0, 0], 
                            [0, 1], 
                            [1, 1], 
                            [1, 0],
                        ]
                    },
                    cells:[[0,1,2],[2,0,3]]
                }
            ])

            // 第五步
            renderer.render()
            
            // 时间变化
            function update(utime){
                if(utime-(update.time||0)>300){
                    renderer.uniforms.uTime = utime;
                    update.time = utime
                }
                requestAnimationFrame(update);
            }
            update(0)

        })()
        
    </script>
</body>
</html>